//---------------------------------------------------------------------
//THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//PARTICULAR PURPOSE.
//---------------------------------------------------------------------

namespace Microsoft.Samples.Alert {
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Drawing.Design;
    using System.Security.Permissions;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.Util;

    /// <summary>
    /// Represents a Button control which asks for confirmation when clicked.
    /// </summary>
    [
    ToolboxData("<{0}:ConfirmButton runat=\"server\"></{0}:ConfirmButton>"),
    AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal),
    AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)
    ]
    public class ConfirmButton : Button {

        // Using a dictionary of Alerts that we store in the context to avoid creating duplicate
        // copies of the same Alert. This key is the key of the context object.
        private static readonly string ContextAlertDictionaryKey =
            typeof(ConfirmButton).AssemblyQualifiedName + "_AlertDictionary";

        /// <summary>
        /// Specify the ID of an Alert control to precisely control the layout of the confirm Alert.
        /// </summary>
        [
        Category("Behavior"),
        Themeable(false),
        DefaultValue(""),
        Description("Specify the ID of an Alert control to precisely control the layout of the confirm Alert."),
        IDReferenceProperty(),
        TypeConverter(typeof(ValidatedControlConverter))
        ]
        public string Alert {
            get {
                object o = ViewState["Alert"];
                return ((o == null) ? String.Empty : (string)o);
            }
            set {
                ViewState["Alert"] = value;
            }
        }

        /// <summary>
        /// If set to false, the button will behave like an ordinary button and won't show a confirm Alert.
        /// </summary>
        [
        Category("Behavior"),
        DefaultValue(true),
        Description("If set to false, the button will behave like an ordinary button and won't show a confirm Alert.")
        ]
        public bool Confirm {
            get {
                object b = (object)ViewState["Confirm"];
                return ((b == null) ? true : (bool)b);
            }
            set {
                ViewState["Confirm"] = value;
            }
        }

        /// <summary>
        /// The text that appears in the confirmation Alert (if the Alert property is empty).
        /// </summary>
        [
        Category("Appearance"),
        DefaultValue(""),
        Description("The text that appears in the confirmation Alert (if the Alert property is empty).")
        ]
        public string ConfirmText {
            get {
                string s = (string)ViewState["ConfirmText"];
                return ((s == null) ? String.Empty : s);
            }
            set {
                ViewState["ConfirmText"] = value;
            }
        }

        public override string OnClientClick {
            get {
                return base.OnClientClick;
            }
            set {
                throw new NotSupportedException("Setting OnClientClick is not supported on ConfirmButton.");
            }
        }

        public override void RenderControl(HtmlTextWriter writer) {
            if (!DesignMode) {
                if (Confirm) {
                    Alert msg = null;
                    // Was an Alert specified explicitly?
                    if (Alert.Length > 0) {
                        // Looking for the Alert in all naming containers.
                        Control parent = NamingContainer;
                        while (parent != null && msg == null) {
                            msg = parent.FindControl(Alert) as Alert;
                            parent = parent.NamingContainer;
                        }
                        if (msg == null) {
                            throw new HttpException(String.Format("Control {0} not found.", Alert));
                        }
                    }
                    else {
                        // Is there an Alert with the same message in the context?
                        Dictionary<string, Alert> alertDictionary = Context.Items[ContextAlertDictionaryKey]
                            as Dictionary<string, Alert>;
                        if (alertDictionary == null) {
                            // The dictionary has not yet been created.
                            alertDictionary = new Dictionary<string, Alert>();
                            Context.Items.Add(ContextAlertDictionaryKey, alertDictionary);
                        }
                        if (alertDictionary.ContainsKey(ConfirmText)) {
                            // Fetching the cached Alert
                            msg = alertDictionary[ConfirmText];
                        }
                        else {
                            // Alert not found in the page cache, creating and caching it.
                            msg = new Alert();
                            msg.ID = UniqueID + "_confirm";
                            msg.Page = Page;
                            msg.EnableViewState = false;
                            msg.Buttons = AlertButtons.YesNo;
                            msg.HorizontalAlign = HorizontalAlign.Center;
                            msg.Width = Unit.Pixel(300);
                            msg.Height = Unit.Pixel(80);
                            LiteralControl LiteralText = new LiteralControl();
                            LiteralText.EnableViewState = false;
                            LiteralText.Text = ConfirmText;
                            msg.Controls.Add(LiteralText);
                            // Store in the page cache
                            alertDictionary[ConfirmText] = msg;
                            // Render the Alert
                            msg.RenderControl(writer);
                        }
                    }
                    base.OnClientClick = "return (" + msg.GetShowClientEvent() + " == true)";
                }
                else {
                    base.OnClientClick = "";
                }
            }
            base.RenderControl(writer);
        }
    }
}